Pythonã²ãŒã ãšã³ãžã³åãã«å ç¢ã§å¹ççãªã¬ã³ããªã³ã°ãã€ãã©ã€ã³ãæ§ç¯ããããã®è©³çްãªè§£èª¬ãã¯ãã¹ãã©ãããã©ãŒã ã®äºææ§ãšææ°ã®ã¬ã³ããªã³ã°æè¡ã«çŠç¹ãåœãŠãŸãã
Pythonã²ãŒã ãšã³ãžã³ïŒã¯ãã¹ãã©ãããã©ãŒã ã§ã®æåã«åããã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã®å®è£
ã²ãŒã ãšã³ãžã³ã®äœæã¯è€éã§ãããããããã®ãã詊ã¿ã§ããããããã²ãŒã ãšã³ãžã³ã®äžå¿ã«ã¯ããã¬ã€ã€ãŒãèŠãããžã¥ã¢ã«ã«ã²ãŒã ããŒã¿ã倿ãã圹å²ãæ ãã¬ã³ããªã³ã°ãã€ãã©ã€ã³ããããŸãããã®èšäºã§ã¯ãPythonããŒã¹ã®ã²ãŒã ãšã³ãžã³ã«ãããã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã®å®è£ ãæ¢æ±ããç¹ã«ã¯ãã¹ãã©ãããã©ãŒã ã®äºææ§ã®å®çŸãšææ°ã®ã¬ã³ããªã³ã°æè¡ã®æŽ»çšã«çŠç¹ãåœãŠãŸãã
ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ãçè§£ãã
ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã¯ã3Dã¢ãã«ããã¯ã¹ãã£ããã®ä»ã®ã²ãŒã ããŒã¿ãåã蟌ã¿ãããããç»é¢ã«è¡šç€ºããã2Dç»åã«å€æããäžé£ã®ã¹ãããã§ããäžè¬çãªã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã¯ãããã€ãã®ã¹ããŒãžã§æ§æãããŸãã
- å ¥åã¢ã»ã³ãã©: ãã®ã¹ããŒãžã¯é ç¹ããŒã¿ïŒäœçœ®ãæ³ç·ããã¯ã¹ãã£åº§æšïŒãåéããããªããã£ãïŒäžè§åœ¢ãç·ãç¹ïŒã«çµã¿ç«ãŠãŸãã
- é ç¹ã·ã§ãŒããŒ: åé ç¹ãåŠçãã倿ïŒäŸïŒã¢ãã«ãã¥ãŒãããžã§ã¯ã·ã§ã³ïŒãå®è¡ããã©ã€ãã£ã³ã°ãèšç®ããé ç¹å±æ§ã倿Žããããã°ã©ã ã§ãã
- ãžãªã¡ããªã·ã§ãŒããŒïŒãªãã·ã§ã³ïŒ: ããªããã£ãå šäœïŒäžè§åœ¢ãç·ããŸãã¯ç¹ïŒãæäœããæ°ããããªããã£ããäœæããããæ¢åã®ããªããã£ããç Žæ£ãããã§ããŸããã¢ãã³ãªãã€ãã©ã€ã³ã§ã¯ããŸã䜿çšãããŸããã
- ã©ã¹ã¿ã©ã€ãº: ããªããã£ãããã©ã°ã¡ã³ãïŒæœåšçãªãã¯ã»ã«ïŒã«å€æããŸããããã«ã¯ãåããªããã£ãã«ãã£ãŠã©ã®ãã¯ã»ã«ãã«ããŒãããããæ±ºå®ããããªããã£ãã®è¡šé¢å šäœã§é ç¹å±æ§ãè£éããããšãå«ãŸããŸãã
- ãã©ã°ã¡ã³ãã·ã§ãŒããŒ: åãã©ã°ã¡ã³ããåŠçãããã®æçµçãªè²ã決å®ããããã°ã©ã ã§ããããã«ã¯ãè€éãªã©ã€ãã£ã³ã°èšç®ããã¯ã¹ãã£ã«ãã¯ã¢ããããã®ä»ã®ãšãã§ã¯ããé »ç¹ã«å«ãŸããŸãã
- åºåããŒãž: ãã©ã°ã¡ã³ãã®è²ããã¬ãŒã ãããã¡å ã®æ¢åã®ãã¯ã»ã«ããŒã¿ãšçµåããããã¹ãã¹ãããã¬ã³ããªã©ã®æäœãå®è¡ããŸãã
ã°ã©ãã£ãã¯ã¹APIã®éžæ
ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã®åºç€ã¯ãéžæããã°ã©ãã£ãã¯ã¹APIã§ããããã€ãã®ãªãã·ã§ã³ããããããããã«é·æãšçæããããŸãã
- OpenGL: é·å¹Žã«ããã£ãŠåºããµããŒããããŠããã¯ãã¹ãã©ãããã©ãŒã APIã§ããOpenGLã¯è±å¯ãªãµã³ãã«ã³ãŒããšããã¥ã¡ã³ããæäŸããŸããå€ãããŒããŠã§ã¢ãå«ãå¹ åºããã©ãããã©ãŒã ã§å®è¡ããå¿ èŠããããããžã§ã¯ãã«é©ããéžæè¢ã§ãããã ãããã®å€ãããŒãžã§ã³ã¯ææ°ã®APIãããå¹çãäœãå ŽåããããŸãã
- DirectX: Microsoftç¬èªã®APIã§ãäž»ã«Windowsããã³Xboxãã©ãããã©ãŒã ã§äœ¿çšãããŸããDirectXã¯åªããããã©ãŒãã³ã¹ãšæå 端ã®ããŒããŠã§ã¢æ©èœãžã®ã¢ã¯ã»ã¹ãæäŸããŸãããã ããã¯ãã¹ãã©ãããã©ãŒã ã§ã¯ãããŸãããWindowsãäž»èŠãŸãã¯å¯äžã®ã¿ãŒã²ãããã©ãããã©ãŒã ã§ããå Žåã«æ€èšããŠãã ããã
- Vulkan: GPUããã现ããå¶åŸ¡ã§ããææ°ã®äœã¬ãã«APIã§ããVulkanã¯åªããããã©ãŒãã³ã¹ãšå¹çãæäŸããŸãããOpenGLãDirectXãããè€éã§ããããåªãããã«ãã¹ã¬ããã®å¯èœæ§ãæäŸããŸãã
- Metal: Appleç¬èªã®iOSããã³macOSçšAPIã§ããDirectXãšåæ§ã«ãMetalã¯åªããããã©ãŒãã³ã¹ãæäŸããŸãããAppleãã©ãããã©ãŒã ã«éå®ãããŸãã
- WebGPU: Webçšã«èšèšãããæ°ããAPIã§ãWebãã©ãŠã¶ã§ææ°ã®ã°ã©ãã£ãã¯ã¹æ©èœãæäŸããŸããWebå šäœã§ã¯ãã¹ãã©ãããã©ãŒã ã§ãã
ã¯ãã¹ãã©ãããã©ãŒã ã®Pythonã²ãŒã ãšã³ãžã³ã§ã¯ãäžè¬çã«OpenGLãŸãã¯Vulkanãæé©ãªéžæè¢ã§ããOpenGLã¯ããå¹ åºãäºææ§ãšç°¡åãªã»ããã¢ãããæäŸããVulkanã¯ããåªããããã©ãŒãã³ã¹ãšããå€ãã®å¶åŸ¡ãæäŸããŸããVulkanã®è€éãã¯ãæœè±¡åã©ã€ãã©ãªã䜿çšããããšã§è»œæžã§ããå¯èœæ§ããããŸãã
ã°ã©ãã£ãã¯ã¹APIã®ããã®Pythonãã€ã³ãã£ã³ã°
Pythonããã°ã©ãã£ãã¯ã¹APIã䜿çšããã«ã¯ããã€ã³ãã£ã³ã°ã䜿çšããå¿ èŠããããŸããããã€ãã®äººæ°ã®ãããªãã·ã§ã³ããããŸãã
- PyOpenGL: OpenGLã§åºã䜿çšãããŠãããã€ã³ãã£ã³ã°ã§ããOpenGL APIã®æ¯èŒçèãã©ãããŒãæäŸãããã®æ©èœã®ã»ãšãã©ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãã
- glfw: (OpenGL Framework) ãŠã£ã³ããŠã®äœæãšå ¥ååŠçã®ããã®è»œéãªã¯ãã¹ãã©ãããã©ãŒã ã©ã€ãã©ãªã§ããPyOpenGLãšçµã¿åãããŠäœ¿çšãããããšããããããŸãã
- PyVulkan: Vulkançšã®ãã€ã³ãã£ã³ã°ã§ããVulkanã¯OpenGLãããæ°ããè€éãªAPIã§ãããããPyVulkanã䜿çšããã«ã¯ã°ã©ãã£ãã¯ã¹ããã°ã©ãã³ã°ã«é¢ããããæ·±ãçè§£ãå¿ èŠã§ãã
- sdl2: (Simple DirectMedia Layer) ã°ã©ãã£ãã¯ã¹ããªãŒãã£ãªãå ¥åãå«ããã«ãã¡ãã£ã¢éçºã®ããã®ã¯ãã¹ãã©ãããã©ãŒã ã©ã€ãã©ãªã§ããOpenGLãVulkanãžã®çŽæ¥çãªãã€ã³ãã£ã³ã°ã§ã¯ãããŸãããããããã®APIã®ãŠã£ã³ããŠãšã³ã³ããã¹ããäœæã§ããŸãã
ãã®äŸã§ã¯ã䜿ãããããšæ©èœã®ãã©ã³ã¹ãåããŠãããããglfwã䜿çšããPyOpenGLã«çŠç¹ãåœãŠãŸãã
ã¬ã³ããªã³ã°ã³ã³ããã¹ãã®ã»ããã¢ãã
ã¬ã³ããªã³ã°ãéå§ããåã«ãã¬ã³ããªã³ã°ã³ã³ããã¹ããã»ããã¢ããããå¿ èŠããããŸããããã«ã¯ããŠã£ã³ããŠãäœæããã°ã©ãã£ãã¯ã¹APIãåæåããããšãå«ãŸããŸãã
import glfw
from OpenGL.GL import *
# Initialize GLFW
if not glfw.init():
raise Exception("GLFW initialization failed!")
# Create a window
window = glfw.create_window(800, 600, "Python Game Engine", None, None)
if not window:
glfw.terminate()
raise Exception("GLFW window creation failed!")
# Make the window the current context
glfw.make_context_current(window)
# Enable v-sync (optional)
glfw.swap_interval(1)
print(f"OpenGL Version: {glGetString(GL_VERSION).decode()}")
ãã®ã³ãŒãã¹ããããã¯ãGLFWãåæåãããŠã£ã³ããŠãäœæãããã®ãŠã£ã³ããŠãçŸåšã®OpenGLã³ã³ããã¹ããšããŠèšå®ãããã£ã¢ãªã³ã°ãé²ãããã«V-SyncïŒåçŽåæïŒãæå¹ã«ããŸããprintã¹ããŒãã¡ã³ãã¯ããããã°ç®çã§çŸåšã®OpenGLããŒãžã§ã³ã衚瀺ããŸãã
é ç¹ãããã¡ãªããžã§ã¯ã (VBO) ã®äœæ
é ç¹ãããã¡ãªããžã§ã¯ã (VBO) ã¯ãé ç¹ããŒã¿ãGPUã«ä¿åããããã«äœ¿çšãããŸããããã«ãããGPUãããŒã¿ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããããã«ãªããæ¯ãã¬ãŒã CPUããããŒã¿ã転éãããããã¯ããã«é«éã«ãªããŸãã
# Vertex data for a triangle
vertices = [
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0
]
# Create a VBO
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, len(vertices) * 4, (GLfloat * len(vertices))(*vertices), GL_STATIC_DRAW)
ãã®ã³ãŒãã¯VBOãäœæããGL_ARRAY_BUFFERã¿ãŒã²ããã«ãã€ã³ãããé ç¹ããŒã¿ãVBOã«ã¢ããããŒãããŸããGL_STATIC_DRAWãã©ã°ã¯ãé ç¹ããŒã¿ãé »ç¹ã«å€æŽãããªãããšã瀺ããŸããlen(vertices) * 4ã®éšåã¯ãé ç¹ããŒã¿ãä¿æããããã«å¿
èŠãªãã€ãåäœã®ãµã€ãºãèšç®ããŸãã
é ç¹é åãªããžã§ã¯ã (VAO) ã®äœæ
é ç¹é åãªããžã§ã¯ã (VAO) ã¯ãé ç¹å±æ§ãã€ã³ã¿ã®ç¶æ ãæ ŒçŽããŸããããã«ã¯ãå屿§ã«é¢é£ä»ããããVBOã屿§ã®ãµã€ãºã屿§ã®ããŒã¿åãããã³VBOå ã§ã®å±æ§ã®ãªãã»ãããå«ãŸããŸããVAOã¯ãç°ãªãé ç¹ã¬ã€ã¢ãŠãéããã°ããåãæ¿ããããšãå¯èœã«ããããšã§ãã¬ã³ããªã³ã°ããã»ã¹ãç°¡çŽ åããŸãã
# Create a VAO
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# Specify the layout of the vertex data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(0)
ãã®ã³ãŒãã¯VAOãäœæãããã€ã³ãããé ç¹ããŒã¿ã®ã¬ã€ã¢ãŠããæå®ããŸããglVertexAttribPointer颿°ã¯ãOpenGLã«VBOå
ã®é ç¹ããŒã¿ãã©ã®ããã«è§£éããããäŒããŸããæåã®åŒæ°ïŒ0ïŒã¯å±æ§ã€ã³ããã¯ã¹ã§ãããé ç¹ã·ã§ãŒããŒå
ã®å±æ§ã®locationã«å¯Ÿå¿ããŸãã2çªç®ã®åŒæ°ïŒ3ïŒã¯å±æ§ã®ãµã€ãºïŒx, y, zã®3ã€ã®floatïŒã§ãã3çªç®ã®åŒæ°ïŒGL_FLOATïŒã¯ããŒã¿åã§ãã4çªç®ã®åŒæ°ïŒGL_FALSEïŒã¯ãããŒã¿ãæ£èŠåãããã¹ããã©ããã瀺ããŸãã5çªç®ã®åŒæ°ïŒ0ïŒã¯ã¹ãã©ã€ãïŒé£ç¶ããé ç¹å±æ§éã®ãã€ãæ°ïŒã§ãã6çªç®ã®åŒæ°ïŒNoneïŒã¯ãVBOå
ã®æåã®å±æ§ã®ãªãã»ããã§ãã
ã·ã§ãŒããŒã®äœæ
ã·ã§ãŒããŒã¯GPUã§å®è¡ãããå®éã®ã¬ã³ããªã³ã°ãè¡ãããã°ã©ã ã§ããã·ã§ãŒããŒã«ã¯ãé ç¹ã·ã§ãŒããŒãšãã©ã°ã¡ã³ãã·ã§ãŒããŒã®2ã€ã®äž»èŠãªã¿ã€ãããããŸãã
# Vertex shader source code
vertex_shader_source = """
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, gl_Position.y, aPos.z, 1.0);
}
"""
# Fragment shader source code
fragment_shader_source = """
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.5, 0.2, 1.0); // Orange color
}
"""
# Create vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertex_shader, vertex_shader_source)
glCompileShader(vertex_shader)
# Check for vertex shader compile errors
success = glGetShaderiv(vertex_shader, GL_COMPILE_STATUS)
if not success:
info_log = glGetShaderInfoLog(vertex_shader)
print(f"ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{info_log.decode()}")
# Create fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragment_shader, fragment_shader_source)
glCompileShader(fragment_shader)
# Check for fragment shader compile errors
success = glGetShaderiv(fragment_shader, GL_COMPILE_STATUS)
if not success:
info_log = glGetShaderInfoLog(fragment_shader)
print(f"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{info_log.decode()}")
# Create shader program
shader_program = glCreateProgram()
glAttachShader(shader_program, vertex_shader)
glAttachShader(shader_program, fragment_shader)
glLinkProgram(shader_program)
# Check for shader program linking errors
success = glGetProgramiv(shader_program, GL_LINK_STATUS)
if not success:
info_log = glGetProgramInfoLog(shader_program)
print(f"ERROR::SHADER::PROGRAM::LINKING_FAILED\n{info_log.decode()}")
glDeleteShader(vertex_shader)
glDeleteShader(fragment_shader)
ãã®ã³ãŒãã¯ãé ç¹ã·ã§ãŒããŒãšãã©ã°ã¡ã³ãã·ã§ãŒããŒãäœæããã³ã³ãã€ã«ããŠãã·ã§ãŒããŒããã°ã©ã ã«ãªã³ã¯ããŸããé ç¹ã·ã§ãŒããŒã¯åã«é ç¹äœçœ®ãæž¡ãããã©ã°ã¡ã³ãã·ã§ãŒããŒã¯ãªã¬ã³ãžè²ãåºåããŸããã³ã³ãã€ã«ãŸãã¯ãªã³ã¯ã®åé¡ãææããããã®ãšã©ãŒãã§ãã¯ãå«ãŸããŠããŸããã·ã§ãŒããŒãªããžã§ã¯ãã¯ãªã³ã¯åŸã«åé€ãããäžèŠã«ãªããŸãã
ã¬ã³ããªã³ã°ã«ãŒã
ã¬ã³ããªã³ã°ã«ãŒãã¯ãã²ãŒã ãšã³ãžã³ã®ã¡ã€ã³ã«ãŒãã§ããã·ãŒã³ãç¶ç¶çã«ç»é¢ã«ã¬ã³ããªã³ã°ããŸãã
# Render loop
while not glfw.window_should_close(window):
# Poll for events (keyboard, mouse, etc.)
glfw.poll_events()
# Clear the color buffer
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
# Use the shader program
glUseProgram(shader_program)
# Bind the VAO
glBindVertexArray(vao)
# Draw the triangle
glDrawArrays(GL_TRIANGLES, 0, 3)
# Swap the front and back buffers
glfw.swap_buffers(window)
# Terminate GLFW
glfw.terminate()
ãã®ã³ãŒãã¯ãã«ã©ãŒãããã¡ãã¯ãªã¢ããã·ã§ãŒããŒããã°ã©ã ã䜿çšããVAOããã€ã³ãããäžè§åœ¢ãæç»ããããã³ããããã¡ãšããã¯ãããã¡ãã¹ã¯ããããŸããglfw.poll_events()颿°ã¯ãããŒããŒãå
¥åãããŠã¹ç§»åãªã©ã®ã€ãã³ããåŠçããŸããglClearColor颿°ã¯èæ¯è²ãèšå®ããglClear颿°ã¯æå®ãããè²ã§ç»é¢ãã¯ãªã¢ããŸããglDrawArrays颿°ã¯ãæå®ãããããªããã£ãã¿ã€ãïŒGL_TRIANGLESïŒã䜿çšããæåã®é ç¹ïŒ0ïŒããéå§ããŠ3ã€ã®é ç¹ãæç»ããããšã§äžè§åœ¢ãæç»ããŸãã
ã¯ãã¹ãã©ãããã©ãŒã ã®èæ ®äºé
ã¯ãã¹ãã©ãããã©ãŒã ã®äºææ§ãå®çŸããã«ã¯ãæ éãªèšç»ãšæ€èšãå¿ èŠã§ããããã«çŠç¹ãåœãŠãã¹ãäž»èŠãªé åãããã€ã瀺ããŸãã
- ã°ã©ãã£ãã¯ã¹APIã®æœè±¡å: æãéèŠãªã¹ãããã¯ãåºç€ãšãªãã°ã©ãã£ãã¯ã¹APIãæœè±¡åããããšã§ããããã¯ãã²ãŒã ãšã³ãžã³ãšAPIã®éã«ã³ãŒãã®å±€ãäœæãããã©ãããã©ãŒã ã«é¢ä¿ãªãäžè²«ããã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããããšãæå³ããŸããbgfxã®ãããªã©ã€ãã©ãªãã«ã¹ã¿ã å®è£ ãããã«é©ããŠããŸãã
- ã·ã§ãŒããŒèšèª: OpenGLã¯GLSLã䜿çšããDirectXã¯HLSLã䜿çšããVulkanã¯SPIR-VãŸãã¯GLSLïŒã³ã³ãã€ã©ã䜿çšïŒã®ããããã䜿çšã§ããŸããglslangValidatorãSPIRV-Crossã®ãããªã¯ãã¹ãã©ãããã©ãŒã ã·ã§ãŒããŒã³ã³ãã€ã©ã䜿çšããŠãåãã©ãããã©ãŒã ã«é©ãã圢åŒã«ã·ã§ãŒããŒã倿ããŸãã
- ãªãœãŒã¹ç®¡ç: ãã©ãããã©ãŒã ã«ãã£ãŠãªãœãŒã¹ã®ãµã€ãºã圢åŒã«ç°ãªãå¶éãããå ŽåããããŸããããšãã°ããã¹ãŠã®ã¿ãŒã²ãããã©ãããã©ãŒã ã§ãµããŒããããŠãããã¯ã¹ãã£å§çž®åœ¢åŒã䜿çšããããå¿ èŠã«å¿ããŠãã¯ã¹ãã£ãã¹ã±ãŒã«ããŠã³ããããããªã©ããããã®éããé©åã«åŠçããããšãéèŠã§ãã
- ãã«ãã·ã¹ãã : CMakeãPremakeã®ãããªã¯ãã¹ãã©ãããã©ãŒã ãã«ãã·ã¹ãã ã䜿çšããŠãç°ãªãIDEãã³ã³ãã€ã©çšã®ãããžã§ã¯ããã¡ã€ã«ãçæããŸããããã«ãããããŸããŸãªãã©ãããã©ãŒã ã§ã²ãŒã ãšã³ãžã³ãç°¡åã«ãã«ãã§ããŸãã
- å ¥ååŠç: ãã©ãããã©ãŒã ã«ãã£ãŠå ¥åããã€ã¹ãšå ¥åAPIãç°ãªããŸããGLFWãSDL2ã®ãããªã¯ãã¹ãã©ãããã©ãŒã å ¥åã©ã€ãã©ãªã䜿çšããŠããã©ãããã©ãŒã éã§äžè²«ããæ¹æ³ã§å ¥åãåŠçããŸãã
- ãã¡ã€ã«ã·ã¹ãã : ãã¡ã€ã«ã·ã¹ãã ãã¹ã¯ãã©ãããã©ãŒã éã§ç°ãªãå ŽåããããŸãïŒäŸïŒã/ããšã\ãïŒãã¯ãã¹ãã©ãããã©ãŒã ã®ãã¡ã€ã«ã·ã¹ãã ã©ã€ãã©ãªãŸãã¯é¢æ°ã䜿çšããŠãããŒã¿ãã«ãªæ¹æ³ã§ãã¡ã€ã«ã¢ã¯ã»ã¹ãåŠçããŸãã
- ãšã³ãã£ã¢ã³: ãã©ãããã©ãŒã ã«ãã£ãŠãã€ãé ïŒãšã³ãã£ã¢ã³ïŒãç°ãªãå ŽåããããŸãããã€ããªããŒã¿ãæ±ãéã«ã¯ããã¹ãŠã®ãã©ãããã©ãŒã ã§æ£ããè§£éãããããã«æ³šæããŠãã ããã
ã¢ãã³ãªã¬ã³ããªã³ã°æè¡
ã¢ãã³ãªã¬ã³ããªã³ã°æè¡ã¯ãã²ãŒã ãšã³ãžã³ã®èŠèŠçå質ãšããã©ãŒãã³ã¹ãå€§å¹ ã«åäžãããããšãã§ããŸããããã«ããã€ãã®äŸãæããŸãã
- é å»¶ã¬ã³ããªã³ã° (Deferred Rendering): ã·ãŒã³ãè€æ°ãã¹ã§ã¬ã³ããªã³ã°ããæåã«ãµãŒãã§ã¹ã®ããããã£ïŒäŸïŒè²ãæ³ç·ã深床ïŒãäžé£ã®ãããã¡ïŒG-ãããã¡ïŒã«æžã蟌ã¿ããã®åŸå¥ã®ãã¹ã§ã©ã€ãã£ã³ã°èšç®ãå®è¡ããŸããé å»¶ã¬ã³ããªã³ã°ã¯ãã©ã€ãã£ã³ã°èšç®ã®æ°ãæžããããšã§ããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸãã
- ç©çããŒã¹ã¬ã³ããªã³ã° (PBR): ç©çããŒã¹ã¢ãã«ã䜿çšããŠãå ãšãµãŒãã§ã¹ã®çžäºäœçšãã·ãã¥ã¬ãŒãããŸããPBRã¯ããããªã¢ã«ã§èŠèŠçã«é åçãªçµæãçã¿åºãããšãã§ããŸãããã¯ã¹ãã£ãªã³ã°ã®ã¯ãŒã¯ãããŒã«ã¯ãSubstance PainterãQuixel Mixerã®ãããªç¹æ®ãªãœãããŠã§ã¢ãå¿ èŠã«ãªãå ŽåããããŸãããããã¯ç°ãªãå°åã®ã¢ãŒãã£ã¹ããå©çšã§ãããœãããŠã§ã¢ã®äŸã§ãã
- ã·ã£ããŠãããã³ã°: å ã®èŠç¹ããã·ãŒã³ãã¬ã³ããªã³ã°ããããšã§ã·ã£ããŠããããäœæããŸããã·ã£ããŠãããã³ã°ã¯ã·ãŒã³ã«å¥¥è¡ããšãªã¢ãªãºã ã远å ã§ããŸãã
- 倧åç §æ (Global Illumination): ã·ãŒã³å ã®å ã®éæ¥ç §æãã·ãã¥ã¬ãŒãããŸãã倧åç §æã¯ã·ãŒã³ã®ãªã¢ãªãºã ãå€§å¹ ã«åäžãããããšãã§ããŸãããèšç®ã³ã¹ããé«ããªããŸãããã¯ããã¯ã«ã¯ãã¬ã€ãã¬ãŒã·ã³ã°ããã¹ãã¬ãŒã·ã³ã°ãã¹ã¯ãªãŒã³ç©ºé倧åç §æïŒSSGIïŒãªã©ããããŸãã
- ãã¹ãããã»ã¹ãšãã§ã¯ã: ã¬ã³ããªã³ã°ãããç»åã«ãã¬ã³ããªã³ã°åŸã«ãšãã§ã¯ããé©çšããŸãããã¹ãããã»ã¹ãšãã§ã¯ãã¯ãã·ãŒã³ã«èŠèŠçãªè¯ããããå ããããç»åã®äžå®å šããä¿®æ£ãããããããã«äœ¿çšã§ããŸããäŸãšããŠã¯ããã«ãŒã ã被åçæ·±åºŠãã«ã©ãŒã°ã¬ãŒãã£ã³ã°ãªã©ããããŸãã
- ã³ã³ãã¥ãŒãã·ã§ãŒããŒ: GPUã§ã®æ±çšèšç®ã«äœ¿çšãããŸããã³ã³ãã¥ãŒãã·ã§ãŒããŒã¯ãããŒãã£ã¯ã«ã·ãã¥ã¬ãŒã·ã§ã³ãç©çã·ãã¥ã¬ãŒã·ã§ã³ãç»ååŠçãªã©ãå¹ åºãã¿ã¹ã¯ã«äœ¿çšã§ããŸãã
äŸïŒåºæ¬çãªã©ã€ãã£ã³ã°ã®å®è£
ã¢ãã³ãªã¬ã³ããªã³ã°æè¡ã宿Œããããã«ãäžè§åœ¢ã«åºæ¬çãªã©ã€ãã£ã³ã°ã远å ããŸãããããŸããåé ç¹ã®æ³ç·ãã¯ãã«ãèšç®ããããããã©ã°ã¡ã³ãã·ã§ãŒããŒã«æž¡ãããã«é ç¹ã·ã§ãŒããŒã倿Žããå¿ èŠããããŸãã
// Vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
Normal = mat3(transpose(inverse(model))) * aNormal;
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
次ã«ãã©ã€ãã£ã³ã°èšç®ãå®è¡ããããã«ãã©ã°ã¡ã³ãã·ã§ãŒããŒã倿Žããå¿ èŠããããŸããåçŽãªæ¡æ£ã©ã€ãã£ã³ã°ã¢ãã«ã䜿çšããŸãã
// Fragment shader
#version 330 core
out vec4 FragColor;
in vec3 Normal;
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
// Normalize the normal vector
vec3 normal = normalize(Normal);
// Calculate the direction of the light
vec3 lightDir = normalize(lightPos - vec3(0.0));
// Calculate the diffuse component
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// Calculate the final color
vec3 result = diffuse * objectColor;
FragColor = vec4(result, 1.0);
}
æåŸã«ãæ³ç·ããŒã¿ãé ç¹ã·ã§ãŒããŒã«æž¡ããå æºäœçœ®ãå æºè²ããªããžã§ã¯ãè²ã®ãŠããã©ãŒã 倿°ãèšå®ããããã«Pythonã³ãŒããæŽæ°ããå¿ èŠããããŸãã
# Vertex data with normals
vertices = [
# Positions # Normals
-0.5, -0.5, 0.0, 0.0, 0.0, 1.0,
0.5, -0.5, 0.0, 0.0, 0.0, 1.0,
0.0, 0.5, 0.0, 0.0, 0.0, 1.0
]
# Create a VBO
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, len(vertices) * 4, (GLfloat * len(vertices))(*vertices), GL_STATIC_DRAW)
# Create a VAO
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# Normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4, ctypes.c_void_p(3 * 4))
glEnableVertexAttribArray(1)
# Get uniform locations
light_pos_loc = glGetUniformLocation(shader_program, "lightPos")
light_color_loc = glGetUniformLocation(shader_program, "lightColor")
object_color_loc = glGetUniformLocation(shader_program, "objectColor")
# Set uniform values
glUniform3f(light_pos_loc, 1.0, 1.0, 1.0)
glUniform3f(light_color_loc, 1.0, 1.0, 1.0)
glUniform3f(object_color_loc, 1.0, 0.5, 0.2)
ãã®äŸã¯ãã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã«åºæ¬çãªã©ã€ãã£ã³ã°ãå®è£ ããæ¹æ³ã瀺ããŠããŸããããè€éãªã©ã€ãã£ã³ã°ã¢ãã«ãã·ã£ããŠãããã³ã°ããã®ä»ã®ã¬ã³ããªã³ã°æè¡ã远å ããããšã§ããã®äŸãæ¡åŒµã§ããŸãã
é«åºŠãªãããã¯
åºæ¬ãè¶ ããŠãã¬ã³ããªã³ã°ãã€ãã©ã€ã³ãããã«åŒ·åã§ããããã€ãã®é«åºŠãªãããã¯ããããŸãã
- ã€ã³ã¹ã¿ã³ã·ã³ã°: åäžã®ãããŒã³ãŒã«ã䜿çšããŠãç°ãªã倿ã䌎ãåããªããžã§ã¯ãã®è€æ°ã®ã€ã³ã¹ã¿ã³ã¹ãã¬ã³ããªã³ã°ããããšã
- ãžãªã¡ããªã·ã§ãŒããŒ: GPUäžã§æ°ãããžãªã¡ããªãåçã«çæããããšã
- ããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒ: 衚é¢ã现ååããŠãããæ»ããã§è©³çްãªã¢ãã«ãäœæããããšã
- ã³ã³ãã¥ãŒãã·ã§ãŒããŒ: ç©çã·ãã¥ã¬ãŒã·ã§ã³ãç»ååŠçãªã©ãæ±çšèšç®ã¿ã¹ã¯ã«GPUã䜿çšããããšã
- ã¬ã€ãã¬ãŒã·ã³ã°: å ç·ã®çµè·¯ãã·ãã¥ã¬ãŒãããŠããããªã¢ã«ãªç»åãçæããããšã(äºææ§ã®ããGPUãšAPIãå¿ èŠ)
- ããŒãã£ã«ãªã¢ãªã㣠(VR) ããã³æ¡åŒµçŸå® (AR) ã¬ã³ããªã³ã°: ç«äœç»åãã¬ã³ããªã³ã°ããä»®æ³ã³ã³ãã³ããçŸå®äžçãšçµ±åããããã®æè¡ã
ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã®ãããã°
ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ã®ãããã°ã¯å°é£ãªå ŽåããããŸããããã«åœ¹ç«ã€ããŒã«ãšãã¯ããã¯ãããã€ã瀺ããŸãã
- OpenGLãããã¬ãŒ: RenderDocãã°ã©ãã£ãã¯ã¹ãã©ã€ããŒã«çµã¿èŸŒãŸãããããã¬ãŒãªã©ã®ããŒã«ã¯ãGPUã®ç¶æ ãæ€æ»ããã¬ã³ããªã³ã°ãšã©ãŒãç¹å®ããã®ã«åœ¹ç«ã¡ãŸãã
- ã·ã§ãŒããŒãããã¬ãŒ: IDEããããã¬ãŒã¯ãã·ã§ãŒããŒã®ãããã°æ©èœãæäŸããããšãå€ããã·ã§ãŒããŒã³ãŒããã¹ãããå®è¡ããŠå€æ°å€ãæ€æ»ã§ããŸãã
- ãã¬ãŒã ãããã¬ãŒ: åã ã®ãã¬ãŒã ããã£ããã£ããŠåæããããã©ãŒãã³ã¹ã®ããã«ããã¯ãã¬ã³ããªã³ã°ã®åé¡ãç¹å®ããŸãã
- ãã®ã³ã°ãšãšã©ãŒãã§ãã¯: ã³ãŒãã«ãã®ã³ã°ã¹ããŒãã¡ã³ãã远å ããŠãå®è¡ãããŒã远跡ããæœåšçãªåé¡ãç¹å®ããŸããAPIåŒã³åºãããšã«
glGetError()ã䜿çšããŠOpenGLãšã©ãŒãåžžã«ãã§ãã¯ããŠãã ããã - ããžã¥ã¢ã«ãããã°: ã·ãŒã³ã®ç°ãªãéšåãç°ãªãè²ã§ã¬ã³ããªã³ã°ãããªã©ãããžã¥ã¢ã«ãããã°æè¡ã䜿çšããŠã¬ã³ããªã³ã°ã®åé¡ãç¹å®ããŸãã
çµè«
Pythonã²ãŒã ãšã³ãžã³ã®ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ãå®è£ ããããšã¯ãè€éã§ããããããã®ããããã»ã¹ã§ãããã€ãã©ã€ã³ã®ç°ãªãã¹ããŒãžãçè§£ããé©åãªã°ã©ãã£ãã¯ã¹APIãéžæããææ°ã®ã¬ã³ããªã³ã°æè¡ã掻çšããããšã§ãå¹ åºããã©ãããã©ãŒã ã§åäœããèŠèŠçã«é åçãªé«æ§èœã²ãŒã ãäœæã§ããŸããã°ã©ãã£ãã¯ã¹APIãæœè±¡åããã¯ãã¹ãã©ãããã©ãŒã ããŒã«ãšã©ã€ãã©ãªã䜿çšããããšã§ãã¯ãã¹ãã©ãããã©ãŒã ã®äºææ§ãåªå ããããšãå¿ããªãã§ãã ããããã®ã³ãããã¡ã³ãã¯ããªãŒãã£ãšã³ã¹ã®ç¯å²ãåºããã²ãŒã ãšã³ãžã³ã®æ°žç¶çãªæåã«è²¢ç®ããã§ãããã
ãã®èšäºã¯ãç¬èªã®ã¬ã³ããªã³ã°ãã€ãã©ã€ã³ãæ§ç¯ããããã®åºçºç¹ãæäŸããŸããããŸããŸãªæè¡ãã¢ãããŒãã詊ããŠãã²ãŒã ãšã³ãžã³ãšã¿ãŒã²ãããã©ãããã©ãŒã ã«æé©ãªãã®ãèŠã€ããŠãã ãããé 匵ã£ãŠãã ããïŒ